<template>
  <base-drawer
    ref="drawer"
    :title="title"
    header-border
    footer-border
    size="medium"
    padding="none"
    :buttons="buttons"
    custom-class="card-drawer"
    @close="onClose">
    <template v-slot:tabs>
      <base-tabs-nav
        v-model="active"
        stretch
        :tabs="tabs"
        class="cart-drawer__tabs" />
    </template>
    <template
      v-if="isIconView"
      v-slot:toolbar>
      <drawer-toolbar
        :is-checked="checked"
        :items="options"
        :selected="selected"
        @check="onCheckAll"
        @import="onImport" />
    </template>
    <div :class="['cart-drawer__main', { 'is-auto': isIconView && !disabled }]">
      <component
        :is="active"
        v-bind="attrs"
        @update="onUpdate"
        @delete="onDelete" />
    </div>
  </base-drawer>
</template>

<script>
/**
 * Cart.vue - Cart 组件
 * =============================================================
 * Created By: Yaohaixiao
 * Update: 2022.11.10
 */
import BaseDrawer from '@/components/BaseDrawer'
import BaseTabsNav from '@/components/BaseTabs/Nav'

import DrawerToolbar from '@/components/Cart/Toolbar'
import DrawerList from '@/components/Cart/List'
import DrawerCode from '@/components/Cart/Code'

import getStorage from '@/utils/storage/getStorage'
import clearStorage from '@/utils/storage/clearStorage'
import { copyToClipboard, createAndDownloadFile } from '@/utils/utils'
import getSymbols from '@yaohaixiao/icons.js/getSymbols'
import paint from '@yaohaixiao/icons.js/paint'

export default {
  name: 'CartDrawer',
  componentName: 'CartDrawer',
  components: {
    BaseDrawer,
    BaseTabsNav,
    DrawerToolbar,
    DrawerList,
    DrawerCode
  },
  props: {
    title: {
      type: String,
      default: '购物车'
    },
    items: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      start: 0,
      last: 0,
      active: 'DrawerList',
      checked: false,
      tabs: [
        {
          label: 'SVG 图标集',
          value: 'DrawerList'
        },
        {
          label: 'JS 源代码',
          value: 'DrawerCode'
        }
      ],
      collections: [],
      imports: [],
      options: [],
      buttons: []
    }
  },
  computed: {
    isIconView() {
      return this.active === 'DrawerList'
    },
    isUnchecked() {
      return this.count === 0
    },
    attrs() {
      const options = this.options
      const isEmpty = this.disabled
      const code = this.code

      if (this.isIconView) {
        return {
          options,
          isEmpty
        }
      } else {
        return { code }
      }
    },
    disabled() {
      return this.options.length === 0
    },
    selected() {
      return this.options.filter((item) => item.checked)
    },
    symbols() {
      return this.selected.map((item) => item.symbol)
    },
    count() {
      return this.selected.length
    },
    code() {
      const iconSet = {
        title: 'Toolkit 图标集',
        code: 'ToolkitSet',
        symbols: this.symbols
      }
      const json = JSON.stringify(iconSet, null, 2)

      return `// Generated by icons.toolkit.vue\nconst ToolkitSet = ${json}\n\nexport default ToolkitSet\n`
    },
    svg() {
      return (
        '<!-- Generated by icons.toolkit.vue -->\n' +
        '<svg id="ijs-icons" aria-hidden="true" style="position:absolute;width:0;height:0;overflow:hidden;">\n' +
        this.symbols.join('\n') +
        '\n</svg>'
      )
    }
  },
  watch: {
    items() {
      this.update()
    },
    count() {
      this.updateButtons()
      this.updateCheckAll()
    }
  },
  created() {
    this.update()
  },
  mounted() {
    this.$subscribe('toolkit:show:cart', this.show)
    this.$subscribe('toolkit:hide:cart', this.hide)
  },
  beforeDestroy() {
    this.$unsubscribe('toolkit:show:cart', this.show)
    this.$unsubscribe('toolkit:hide:cart', this.hide)
    this.$broadcast('toolkit:show:toolbar')
  },
  methods: {
    update() {
      this.collections = this.items.map((symbol) => {
        return {
          checked: true,
          isBuiltIn: true,
          symbol
        }
      })

      this.options = this.collections.concat(this.imports)
      this.updateCheckAll()
      this.updateButtons()
    },
    draw() {
      const defaults = getSymbols()
      let storage = getStorage('toolkit:icons')
      let symbols = []

      if (!storage) {
        return false
      }

      storage = JSON.parse(storage)

      symbols = storage.filter((symbol) => {
        return !defaults.includes(symbol)
      })

      paint(symbols)
    },
    updateCheckAll() {
      this.checked = this.count > 0
    },
    updateButtons() {
      this.buttons = [
        {
          name: 'cancel',
          text: '取消',
          size: 'small'
        },
        {
          name: 'clean',
          text: '清空',
          icon: 'trash',
          disabled: this.disabled,
          action: () => {
            this.clear()
          }
        },
        {
          name: 'download',
          text: '下载',
          icon: 'download',
          disabled: this.isUnchecked,
          action: () => {
            this.download()
          }
        },
        {
          name: 'confirm',
          text: '复制',
          icon: 'copy',
          size: 'small',
          type: 'primary',
          disabled: this.isUnchecked,
          action: () => {
            this.copy()
          }
        }
      ]
    },
    uncheckAll() {
      const options = this.collections.concat(this.imports)

      this.options = options.map((item) => {
        const { isBuildIn, symbol } = item

        return {
          checked: false,
          isBuildIn,
          symbol
        }
      })
    },
    checkAll() {
      const options = this.collections.concat(this.imports)

      this.options = options.map((item) => {
        const { isBuildIn, symbol } = item

        return {
          checked: true,
          isBuildIn,
          symbol
        }
      })
    },
    doImport(symbols) {
      paint(symbols)

      symbols.forEach((symbol) => {
        this.imports.push({
          checked: true,
          isBuildIn: false,
          symbol
        })
      })

      this.update()
    },
    doDelete(symbol) {
      const imports = [...this.imports]

      this.imports = imports.filter((item) => {
        return item.symbol !== symbol
      })

      this.update()
    },
    clear() {
      const $icons = document.querySelector('#ijs-icons')
      const imports = [...this.imports]

      clearStorage('toolkit:icons')

      imports.forEach((item) => {
        const PATTERN_ID = /id="(.*?)"/
        const match = item.symbol.match(PATTERN_ID)
        const id = match && match[1] ? match[1] : ''
        const $icon = document.querySelector(`#${id}`)

        if (item.isBuildIn || !$icon) {
          return false
        }

        $icons.removeChild($icon)
      })

      this.imports = []

      this.$message.success({
        round: true,
        message: `购物车已清空！`
      })

      this.$broadcast('toolkit:clean:cart')
    },
    copy() {
      copyToClipboard(this.isIconView ? this.svg : this.code)
      this.$message.success({
        round: true,
        message: `代码已复制！`
      })
    },
    download() {
      if (this.isIconView) {
        createAndDownloadFile('svg-icon-set.svg', this.svg)
      } else {
        createAndDownloadFile('svg-icon-set.js', this.code)
      }
    },
    show() {
      this.draw()
      this.$refs.drawer.open()
    },
    hide() {
      this.$refs.drawer.close()
    },
    close() {
      setTimeout(() => {
        this.$broadcast('toolkit:show:toolbar')
      }, 300)
    },
    onCheckAll(checked, isIndeterminate) {
      if (isIndeterminate || (checked && !isIndeterminate)) {
        this.checkAll()
      } else {
        this.uncheckAll()
      }
    },
    onImport(symbols) {
      this.doImport(symbols)
    },
    onUpdate(options) {
      this.options = [...options]
    },
    onDelete(symbol) {
      this.doDelete(symbol)
    },
    onClose() {
      this.close()
    }
  }
}
</script>

<style scoped lang="less">
@import 'drawer';
</style>
